<template>
  <!-- v-container 是 Vuetify 提供的布局组件，用于创建一个流体布局的容器。 -->
  <v-container fluid>
    <!-- 表格标题 -->
    <v-row align="center" justify="center" class="header-row">
      <v-col cols="2" class="d-flex align-center justify-center">
        <!-- header-item 是用于显示"端口"的样式。 -->
        <div class="header-item">端口</div>
      </v-col>
      <v-col cols="4" class="d-flex align-center justify-center">
        <div class="arrow-item"><span class="double-arrow">&lt;--------------></span></div>
      </v-col>
      <!-- 该列用于显示双向箭头指示，表示端口与远程 IP 之间的关系。 -->
      <v-col cols="2" class="d-flex align-center justify-center">
        <div class="header-item">远程IP</div>
      </v-col>
      <v-col cols="1" class="d-flex align-center justify-center">
        <div class="header-item">:</div>
      </v-col>
      <v-col cols="2" class="d-flex align-center justify-center">
        <div class="header-item">远程端口</div>
      </v-col>
      <v-col cols="1"></v-col> <!-- 占位，用于“确认/删除”按钮 -->
    </v-row>

    <!-- 动态数据行 -->
    <v-row
        v-for="(row, index) in rows"
        :key="index"
        align="center"
        justify="center"
        class="data-row"
    >
    <!-- 这一列包含一个输入框，用于输入端口。如果该行已确认（confirmed 为 true），则显示该端口的值。 -->
      <v-col cols="2" class="d-flex align-center justify-center">
        <v-text-field
            v-if="!row.confirmed"
            v-model="row.port"
            dense
            hide-details
        ></v-text-field>
        <div v-else>{{ row.port }}</div>
      </v-col>

      <v-col cols="4" class="d-flex align-center justify-center">
        <div class="arrow-item"><span class="double-arrow">&lt;--------------></span></div>
      </v-col>

      <v-col cols="2" class="d-flex align-center justify-center">
        <v-text-field
            v-if="!row.confirmed"
            v-model="row.remoteIp"
            dense
            hide-details
        ></v-text-field>
        <div v-else>{{ row.remoteIp }}</div>
      </v-col>

      <v-col cols="1" class="d-flex align-center justify-center">
        <div class="header-item">:</div>
      </v-col>

      <!-- 输入远程端口的字段。 -->
      <v-col cols="2" class="d-flex align-center justify-center">
        <v-text-field
            v-if="!row.confirmed"
            v-model="row.remotePort" dense hide-details>
        </v-text-field>
        <div v-else>{{ row.remotePort }}</div>
      </v-col>
      <!-- 该列包含一个按钮，用于确认或删除行。按钮的颜色和图标根据行的确认状态变化。 -->
      <v-col cols="1" class="d-flex align-center justify-center">
        <v-btn icon @click="row.confirmed ? deleteRow(index) : confirmRow(index)"
               :color="row.confirmed ? 'red' : 'primary'">
          <v-icon>{{ row.confirmed ? 'mdi-close' : 'mdi-check' }}</v-icon>
        </v-btn>
      </v-col>
    </v-row>

    <!-- 该按钮用于添加新行，type 控制按钮的颜色和图标。 -->
    <v-row align="center" justify="center" class="mt-3">
      <v-btn icon :color="type ? 'grey' : 'red'" class="add-btn" @click="addRow">
        <v-icon> {{ type ? 'mdi-plus' : 'mdi-close' }}</v-icon>
      </v-btn>
    </v-row>

    <!-- v-snackbar 用于显示提示信息。其显示状态、颜色、文本、图标等均通过 snackbar 对象控制。 -->
    <v-snackbar
        v-model="snackbar.show"
        :color="snackbar.color"
        :timeout="1000"
        multi-line
        top
    >
      <template>
        <v-icon v-if="snackbar.icon" :color="snackbar.iconColor">{{ snackbar.icon }}</v-icon>
      </template>
      {{ snackbar.text }}
      <v-spacer></v-spacer>
    </v-snackbar>
  </v-container>
</template>
<script>
// 定义了两个正则表达式，用于验证端口和 IP 地址的格式。
const portRule = /^([0-9]|[0-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/
const ipRule = /^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
export default {
  data() {
    return {
      // rows 数组用于保存每一行的数据。type 用于控制添加行的状态。 snackbar 对象用于控制提示信息的显示状态和内容。
      rows: [],
      type: true,
      snackbar: {
        show: false,
        color: '',
        text: '',
        icon: '',
        iconColor: ''
      }
    };
  },
  methods: {
    // allRowsConfirmed 方法检查所有行是否都已确认，如果有未确认的行，设置 type 为 false。
    allRowsConfirmed() {
      this.type = true;
      if (this.rows.length === 0) return;
      for (let r in this.rows) {
        if (!this.rows[r].confirmed) {
          // console.log(this.rows[r].confirmed);
          return this.type = false;
        }
      }
    },
    // addRow 方法根据 type 的状态添加或删除行，并检查所有行的确认状态。
    addRow() {
      if (this.type) this.rows.push({port: '', remoteIp: '', remotePort: '', confirmed: false});
      else this.deleteRow(this.rows.length - 1);
      this.allRowsConfirmed();
    },
    // confirmRow 方法用于确认行数据的有效性，若有效则设置 confirmed 为 true，否则显示错误信息。
    confirmRow(index) {
      const row = this.rows[index];
      if (row.port && row.remoteIp && row.remotePort) {
        if (!(portRule.test(row.port) && portRule.test(row.remotePort))) {
          this.setSnackBarFalse('端口号格式有误');
          return;
        } else if (!ipRule.test(row.remoteIp)) {
          this.setSnackBarFalse('IP格式有误');
          return;
        } else {
          this.rows[index].confirmed = true;
          this.setSnackBarTrue('添加成功');
        }
      } else {
        this.setSnackBarFalse('输入项不能为空!');
        return;
      }
      this.allRowsConfirmed();
    },
    // deleteRow 方法删除指定索引的行。
    deleteRow(index) {
      this.rows.splice(index, 1);
      this.allRowsConfirmed();
    },
    // returnData 方法触发 save 事件，传递当前的 rows 数据。
    returnData() {
      this.$emit('save', this.rows);
    },
    // setSnackBar 方法用于设置 snackbar 的显示状态和内容。
    setSnackBar(show, color, text, icon, iconColor) {
      this.snackbar.show = show;
      this.snackbar.color = color;
      this.snackbar.text = text;
      this.snackbar.icon = icon;
      this.snackbar.iconColor = iconColor;
    },
    // setSnackBarTrue 和 setSnackBarFalse 用于设置成功和错误的 snackbar 内容。
    setSnackBarTrue(text) {
      this.setSnackBar(true, 'success', text, 'mdi-check', 'green');
    },
    setSnackBarFalse(text) {
      this.setSnackBar(true, 'error', text, 'mdi-close-circle', 'red');
    },
  },
}; 
// Vue.js 组件实现了一个动态可编辑的端口管理表格，用户可以添加、确认或删除端口信息。通过输入验证和提示信息，确保用户输入的有效性，使用 Vue 的响应式特性动态更新 UI。
</script>
<style scoped> .header-row, .data-row {
  margin-bottom: 10px;
}

.header-item, .arrow-item {
  font-weight: bold;
}

.arrow-item {
  font-size: 1.5em; /* 根据需要调整箭头的大小 */
}

.double-arrow {
  display: inline-block;
  transform: scaleX(-1); /* 水平方向反转箭头 */
}

.add-btn {
  background-color: white;
  box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.3);
} </style>
